#!/usr/bin/env python
#
# This software is licensed under the terms of the GNU General Public
# License version 2, as published by the Free Software Foundation, and
# may be copied, distributed, and modified under those terms.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# this script is used to generate 'android/avd/hw-config.h' by
# parsing 'android/avd/hardware-properties.ini'
#
#
import  sys, os, string, re

# location of source file, relative to current program directory
relativeSourcePath = "../avd/hardware-properties.ini"

# location of target file, relative to current program directory
relativeTargetPath = "../avd/hw-config-defs.h"

def quoteStringForC(str):
    """quote a string so it can be used in C"""
    return '\\"'.join('"'+p+'"' for p in str.split('"'))

# a dictionary that maps item types as they appear in the .ini
# file into macro names in the generated C header
#
typesToMacros = {
    'integer': 'HWCFG_INT',
    'string': 'HWCFG_STRING',
    'boolean': 'HWCFG_BOOL',
    'diskSize': 'HWCFG_DISKSIZE',
    'double': 'HWCFG_DOUBLE'
    }

# the list of macro names
macroNames = typesToMacros.values()

# target program header
targetHeader = """\
/* this file is automatically generated from 'hardware-properties.ini'
 * DO NOT EDIT IT. To re-generate it, use android/tools/gen-hw-config.py'
 */
"""

# locate source and target
programDir = os.path.dirname(sys.argv[0])
if len(sys.argv) != 3:
    print "Usage: %s source target\n" % os.path.basename(sys.argv[0])
    sys.exit(1)

sourceFile = sys.argv[1]
targetFile = sys.argv[2]

# parse the source file and record items
# I would love to use Python's ConfigParser, but it doesn't
# support files without sections, or multiply defined items
#
items    = []
lastItem = None

class Item:
    def __init__(self,name):
        self.name     = name
        self.type     = type
        self.default  = None
        self.abstract = ""
        self.description = ""
        self.enum_values = []

    def add(self,key,val):
        if key == 'type':
            self.type = val
        elif key == 'enum':
            # Build list of enumerated values
            self.enum_values = [ s.strip() for s in val.split(',') ]
            # If default value has been already set, make sure it's in the list
            if self.default and not self.default in self.enum_values:
                print "Property '" + self.name + "': Default value '" + self.default + "' is missing in enum: ",
                print self.enum_values,
                sys.exit(1)
        elif key == 'default':
            # If this is an enum, make sure that default value is in the list.
            if val and self.enum_values and not val in self.enum_values:
                print "Property '" + self.name + "': Default value '" + val + "' is missing in enum: ",
                print self.enum_values,
                sys.exit(1)
            else:
                self.default = val
        elif key == 'abstract':
            self.abstract = val
        elif key == 'description':
            self.description = val

for line in open(sourceFile):
    line = line.strip()
    # ignore empty lines and comments
    if len(line) == 0 or line[0] in ";#":
        continue
    key, value = line.split('=')

    key   = key.strip()
    value = value.strip()

    if key == 'name':
        if lastItem: items.append(lastItem)
        lastItem = Item(value)
    else:
        lastItem.add(key, value)

if lastItem:
    items.append(lastItem)

if targetFile == '--':
    out = sys.stdout
else:
    out = open(targetFile,"wb")

out.write(targetHeader)

# write guards to prevent bad compiles
for m in macroNames:
    out.write("""\
#ifndef %(macro)s
#error  %(macro)s not defined
#endif
""" % { 'macro':m })
out.write("\n")

for item in items:
    if item.type == None:
        sys.stderr.write("ignoring config item with no type '%s'\n" % item.name)
        continue

    if not typesToMacros.has_key(item.type):
        sys.stderr.write("ignoring config item with unknown type '%s': '%s'\n" % \
                (item.type, item.name))
        continue

    if item.default == None:
        sys.stderr.write("ignoring config item with no default '%s' */" % item.name)
        continue

    # convert dots into underscores
    varMacro   = typesToMacros[item.type]
    varNameStr = quoteStringForC(item.name)
    varName    = item.name.replace(".","_")
    varDefault = item.default
    varAbstract = quoteStringForC(item.abstract)
    varDesc     = quoteStringForC(item.description)

    if item.type in [ 'string', 'boolean', 'diskSize' ]:
        # quote default value for strings
        varDefault = quoteStringForC(varDefault)

    out.write("%s(\n  %s,\n  %s,\n  %s,\n  %s,\n  %s)\n\n" % \
            (varMacro,varName,varNameStr,varDefault,varAbstract,varDesc))


for m in macroNames:
    out.write("#undef %s\n" % m)

out.write("/* end of auto-generated file */\n")
out.close()
